package com.simplemobiletools.camera.utils;

import android.annotation.SuppressLint;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.simplemobiletools.camera.R;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class Adapter {
    public abstract static class Subject<Data>
            extends RecyclerView.Adapter<ViewHolder<Data>>
            implements View.OnClickListener, View.OnLongClickListener, Callback<Data> {

        private final List<Data> mList = new ArrayList<>();
        private final Listener<Data> mListener;

        public Subject() {
            this(null, null);
        }

        public Subject(Listener<Data> listener) {
            this(null, listener);
        }

        public Subject(List<Data> list) {
            this(list, null);
        }

        public Subject(List<Data> list, Listener<Data> listener) {
            if (list != null) {
                this.mList.addAll(list);
            }
            this.mListener = listener;
        }

        @Override
        public void onClick(View v) {
            if (v == null) return;
            if (mListener == null) return;
            Object tag = v.getTag(getTag());
            if (tag instanceof ViewHolder) {
                ViewHolder<Data> temp = (ViewHolder<Data>) tag;
                mListener.onItemClick(temp, mList.get(temp.getAdapterPosition()));
            }
        }

        @Override
        public boolean onLongClick(View v) {
            if (v == null) return false;
            if (mListener == null) return false;
            Object tag = v.getTag(getTag());
            if (tag instanceof ViewHolder) {
                ViewHolder<Data> temp = (ViewHolder<Data>) tag;
                mListener.onItemLongClick(temp, mList.get(temp.getAdapterPosition()));
            }
            return false;
        }

        @Override
        public int getItemViewType(int position) {
            return getItemViewType(position, mList.get(position));
        }

        protected abstract int getItemViewType(int position, Data data);
        @NonNull
        @Override
        public ViewHolder<Data> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            final View inflate = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
            final ViewHolder<Data> viewHolder = onCreateViewHolder(inflate, viewType);
            inflate.setTag(getTag(), viewHolder);
            inflate.setOnClickListener(this);
            inflate.setOnLongClickListener(this);
            viewHolder.callback = this;
            return viewHolder;
        }

        public abstract ViewHolder<Data> onCreateViewHolder(View contentView, int viewType);

        @Override
        public void onBindViewHolder(@NonNull ViewHolder<Data> holder, int position) {
            holder.bind(mList.get(position));
        }

        @Override
        public int getItemCount() {
            return mList.size();
        }

        public List<Data> getItems() {
            return mList;
        }

        public int getTag() {
            return R.id.tag_view_holder;
        }

        public void add(Data data) {
            mList.add(data);
            notifyItemInserted(mList.size() - 1);
        }

        @SafeVarargs
        public final void addAll(Data... array) {
            if (array.length > 0) {
                int start = mList.size();
                int offSet = array.length;
                mList.addAll(Arrays.asList(array));
                notifyItemRangeChanged(start, offSet);
            }
        }

        public void addAll(Collection<Data> collection) {
            if (collection.size() > 0) {
                int start = mList.size();
                int offSet = collection.size();
                mList.addAll(collection);
                notifyItemRangeChanged(start, offSet);
            }
        }

        @SuppressLint("NotifyDataSetChanged")
        public void clear() {
            mList.clear();
            notifyDataSetChanged();
        }
        @SafeVarargs
        @SuppressLint("NotifyDataSetChanged")
        public final void replaceAll(Data... array) {
            if (array.length > 0) {
                mList.clear();
                mList.addAll(Arrays.asList(array));
                notifyDataSetChanged();
            }
        }
        @SuppressLint("NotifyDataSetChanged")
        public void replaceAll(Collection<Data> collection) {
            if (collection.size() > 0) {
                mList.clear();
                mList.addAll(collection);
                notifyDataSetChanged();
            }
        }

        public void replace(int position, Data data) {
            int size = mList.size();
            if (position > 0 && position < size) {
                // 进行数据的移除
                mList.remove(position);
                //更新
                mList.add(position, data);
                // 通知这个坐标下的数据有更新
                notifyItemChanged(position);
            }
        }

        @Override
        public void update(Data data, ViewHolder<Data> viewHolder) {
            // 得到当前ViewHolder的坐标
            int pos = viewHolder.getAdapterPosition();
            if (pos >= 0) {
                replace(pos, data);
            }
        }

    }

    public abstract static class ViewHolder<Data> extends RecyclerView.ViewHolder {

        Data mData = null;

        Callback<Data> callback = null;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
        }

        void bind(Data data) {
            this.mData = data;
            onBind(data);
        }

        public abstract void onBind(Data data);


        void updateData(Data data) {
            if (callback == null) return;
            callback.update(data, this);
        }
    }

    public interface Callback<Data> {
        void update(Data data, ViewHolder<Data> viewHolder);
    }

    public interface Listener<Data> {
        void onItemClick(ViewHolder<Data> viewHolder, Data data);

        boolean onItemLongClick(ViewHolder<Data> viewHolder, Data data);
    }

    public abstract static class AbstractListener<Data> implements Listener<Data> {
        @Override
        public void onItemClick(ViewHolder<Data> viewHolder, Data data) {

        }

        @Override
        public boolean onItemLongClick(ViewHolder<Data> viewHolder, Data data) {
            return false;
        }
    }
}
